#include "dynobject.h"
#include "dyntype.h"
#include <string.h>
// .........................................................

DynObject::DynObject()
{
  this->dyntype = 0;
}

DynObject::DynObject(DynType* dyntype, const membuf_t& buf)
{
  this->set_o_buf(dyntype, buf);
}

DynObject::DynObject(DynType* dyntype)
{
  this->set_o_buf(dyntype, dyntype->none_rep);
}

DynObject::~DynObject()
{
  delete [] o_buf.buf;
}

DynObject::DynObject(const DynObject& o) {
  this->set_o_buf(o.dyntype, o.o_buf);
}

DynObject& DynObject::operator=(const DynObject& o) {
  set_o_buf(o.dyntype, o.o_buf);
  return *this;
}

void DynObject::set_o_buf(const membuf_t& b)
{
  this->set_o_buf(dyntype, b);
}

void DynObject::set_o_buf(DynType* dt)
{
  this->set_o_buf(dt, dt->none_rep);
}

void DynObject::set_o_buf(DynType* dt, const membuf_t& b)
{
  this->dyntype = dt;
  delete [] o_buf.buf;
  o_buf.buf_len = b.buf_len;
  o_buf.buf = new char[o_buf.buf_len];
  memcpy(o_buf.buf, b.buf, o_buf.buf_len);
}

void DynObject::print(ostream& out) const
{
  if (dyntype) {
    dyntype->print_obj(out, o_buf);
  } else {
    out << "None";
  }
}

bool DynObject::equal(const DynObject& o) const
{
  if (dyntype != o.dyntype) {
    throw Error(__FILE__, __LINE__, "DynObject::equal: dyntype mismatch");
  }
  
  if (this->o_buf.buf == 0) {
    throw Error(__FILE__, __LINE__, 
		"DynObject::equal: this->o_buf not initialized");
  }

  if (o.o_buf.buf == 0) {
    throw Error(__FILE__, __LINE__, 
		"DynObject::less: o.o_buf not initialized");
  }
  
  return dyntype->equal_obj(this->o_buf, o.o_buf);
} 

bool DynObject::less(const DynObject& o) const
{
  if (dyntype != o.dyntype) {
    ostringstream msg;
    msg << "DynObject::less: dyntype mismatch: " << dyntype->get_name() 
	<< " " << o.dyntype->get_name();
    throw Error(__FILE__, __LINE__, msg.str());
  }

  if (this->o_buf.buf == 0) {
    throw Error(__FILE__, __LINE__, 
		"DynObject::less: this->o_buf not initialized");
  }

  if (o.o_buf.buf == 0) {
    throw Error(__FILE__, __LINE__, 
		"DynObject::less: o.o_buf not initialized");
  }
  
  return dyntype->less_obj(this->o_buf, o.o_buf);
}

bool DynObject::is_none() const
{
  return dyntype == 0 || dyntype->is_none_rep(o_buf);
}
